//
// Copyright (c) 2009 All Right Reserved
//
// vl
//
// 2009-01-01
// Contains ...
namespace LargoCommon.Music
{
using Abstract;
using JetBrains.Annotations;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Xml.Linq;
///
/// Harmonic Motive.
///
[Serializable]
public sealed class HarmonicBar
{
#region Fields
///
/// Harmonic Structures.
///
[NonSerialized]
private IList harmonicStructures;
///
/// Rhythmic Structure.
///
private RhythmicStructure rhythmicStructure;
///
/// Harmonic Modality.
///
private HarmonicModality harmonicModality;
///
/// Simple structural Outline.
///
private string simpleStructuralOutline;
///
/// Structural Outline.
///
private string structuralOutline;
///
/// The bar metric code.
///
private string barMetricCode;
///
/// The harmonic modality code.
///
private string harmonicModalityCode;
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
/// The given bar number.
/// The original bar number.
public HarmonicBar(int givenBarNumber, int originalBarNumber) {
this.RhythmicBehavior = new RhythmicBehavior();
this.HarmonicBehavior = new HarmonicBehavior();
this.harmonicStructures = new List();
this.BarNumber = givenBarNumber;
this.OriginalBarNumber = originalBarNumber;
}
///
/// Initializes a new instance of the class.
///
/// The given header.
/// The given bar.
public HarmonicBar(MusicalHeader givenHeader, HarmonicBar givenBar) {
this.Header = givenHeader; //// Convert given bar under given (style) header...
this.RhythmicBehavior = givenBar.RhythmicBehavior;
this.HarmonicBehavior = givenBar.HarmonicBehavior;
this.harmonicStructures = new List();
this.BarNumber = givenBar.BarNumber;
this.OriginalBarNumber = givenBar.OriginalBarNumber;
this.HarmonicModality = givenBar.HarmonicModality;
this.RhythmicStructure = givenBar.RhythmicStructure.ConvertToSystem(givenHeader.System.RhythmicSystem);
this.RhythmicShape = this.RhythmicStructure.GetRhythmicShape;
int idx = 0;
var distances = this.RhythmicShape.BitDistances;
foreach (var givenHarStruct in givenBar.harmonicStructures) {
var harStruct = (HarmonicStructure)givenHarStruct.Clone();
if (idx < distances.Count) {
harStruct.Length = distances[idx++];
}
this.harmonicStructures.Add(harStruct);
}
//// var rsystem = this.RhythmicSystemFromStructures;
this.RhythmicShape = this.RhythmicShapeFromStructures(givenHeader.System.RhythmicSystem);
this.barMetricCode = this.BarMetricFromStructures(givenHeader.System.RhythmicSystem);
}
///
/// Initializes a new instance of the class.
///
/// The given header.
/// The mark bar.
public HarmonicBar(MusicalHeader givenHeader, XElement markHarmony) {
int barNumber = XmlSupport.ReadIntegerAttribute(markHarmony.Attribute("Number"));
int originalBarNumber = XmlSupport.ReadIntegerAttribute(markHarmony.Attribute("OriginalNumber"));
this.RhythmicBehavior = new RhythmicBehavior();
this.HarmonicBehavior = new HarmonicBehavior();
this.harmonicStructures = new List();
this.BarNumber = barNumber;
this.OriginalBarNumber = originalBarNumber;
this.Header = givenHeader;
var xstructure = markHarmony.Elements("Structure");
if (xstructure != null) {
//// var xstructure = xElement.Elements("Structure");
StringBuilder sb = new StringBuilder();
foreach (var xst in xstructure) {
var code = (string)xst.Attribute("Code");
var start = (int)xst.Attribute("Start");
var length = (int)xst.Attribute("Length");
var st = new HarmonicStructure(this.Header.System.HarmonicSystem, code) {
BitFrom = (byte)start,
Length = (byte)length
};
var shortcut = XmlSupport.ReadStringAttribute(xst.Attribute("Shortcut"));
st.DetermineBehavior();
st.Shortcut = shortcut;
//// st.Base = chordBase;
this.AddStructure(st);
sb.Append(shortcut);
sb.Append(",");
}
//// bar.RhythmicStructure;
this.StructuralOutline = sb.ToString();
var rhyStruct = this.RhythmicStructure;
this.RhythmicShape = new RhythmicShape(rhyStruct.RhythmicSystem.Order, rhyStruct);
this.SetBarMetricCode(this.RhythmicShape.GetStructuralCode);
}
}
///
/// Initializes a new instance of the class.
///
/// The given header.
/// The harmonic structure.
public HarmonicBar(MusicalHeader givenHeader, HarmonicStructure harmonicStructure) {
this.Header = givenHeader;
this.SetStructure(harmonicStructure);
}
#endregion
#region Properties - Xml
/// Gets Xml representation.
/// Property description.
public XElement GetXElement {
get {
var xelement = new XElement("Harmony");
xelement.Add(new XAttribute("Length", this.Length));
foreach (var harStruct in this.HarmonicStructures) {
var xstruct = harStruct.GetXElement;
xelement.Add(xstruct);
}
return xelement;
}
}
#endregion
#region Main Properties
///
/// Gets or sets the musical header.
///
///
/// The musical header.
///
public MusicalHeader Header { get; set; }
///
/// Gets or sets the Bar Number In Motive.
///
///
/// Property description.
///
public int BarNumber { get; set; }
///
/// Gets or sets the bar number.
///
///
/// The bar number.
///
public int OriginalBarNumber { get; set; }
///
/// Gets or sets the harmonic structures.
///
///
/// The harmonic structures.
///
public IList HarmonicStructures {
get {
Contract.Ensures(Contract.Result>() != null);
if (this.harmonicStructures == null) {
throw new InvalidOperationException("Harmonic structures are null.");
}
return this.harmonicStructures;
}
set => this.harmonicStructures = value ?? throw new ArgumentException("Argument cannot be empty.", nameof(value));
}
/// Gets a value indicating whether if bar is empty.
/// Property description.
/// Returns value.
public bool IsEmpty => this.HarmonicStructures.Count == 0;
/// Gets unique identifier.
/// Property description.
public string UniqueIdentifier {
get {
var ident = new StringBuilder();
foreach (var b in
from ms in this.HarmonicStructures where ms != null from b in ms.GetStructuralCode select b) {
ident.Append(b); //// ElementSchema, DecimalNumber, ms.StructuralCode
}
return ident.ToString();
}
}
///
/// Gets or sets the Harmonic Modality.
///
///
/// Property description.
///
public HarmonicModality HarmonicModality {
get {
if (this.harmonicModality != null) {
return this.harmonicModality;
}
var modalityCode = this.GetHarmonicModalityCode;
if (string.IsNullOrEmpty(modalityCode)) {
return this.harmonicModality;
}
const byte order = DefaultValue.HarmonicOrder; //// this.harMotiveBar.HarmonicMotive.THarmonicMotive.THarmonicCore.HarmonicOrder;
var hs = HarmonicSystem.GetHarmonicSystem(order);
this.harmonicModality = HarmonicModality.GetNewHarmonicModality(hs, modalityCode);
return this.harmonicModality;
}
set => this.harmonicModality = value;
}
///
/// Gets or sets the harmonic motive.
///
///
/// The harmonic motive.
///
public HarmonicMotive HarmonicMotive { get; set; }
#endregion
#region Derived Properties
///
/// Gets or sets the simple structural outline.
///
///
/// Property description.
///
public string SimpleStructuralOutline {
get {
if (!string.IsNullOrEmpty(this.simpleStructuralOutline)) {
return this.simpleStructuralOutline;
}
var sb = new StringBuilder();
//// HarmonicModality modality = this.HarmonicModality;
foreach (var harStruct in this.HarmonicStructures) {
if (sb.Length > 0) {
sb.Append(" ");
}
sb.Append(harStruct.Shortcut);
}
this.simpleStructuralOutline = sb.ToString();
return this.simpleStructuralOutline;
}
set => this.simpleStructuralOutline = value;
}
///
/// Gets the outline.
///
///
/// The outline.
///
[UsedImplicitly]
public string Outline => $"{this.BarNumber}/{this.StructuralOutline}";
///
/// Gets or sets HarmonicStructureOutline.
///
/// General musical property.
public string StructuralOutline {
get {
if (this.structuralOutline != null) {
return this.structuralOutline;
}
var sb = new StringBuilder();
//// HarmonicModality modality = this.HarmonicModality;
foreach (var harStruct in this.HarmonicStructures) {
if (sb.Length > 0) {
sb.Append(" ");
}
sb.Append(harStruct.Shortcut);
sb.Append(string.Format(CultureInfo.InvariantCulture, "({0})", harStruct.Length.ToString(CultureInfo.InvariantCulture)));
}
this.structuralOutline = sb.ToString();
return this.structuralOutline;
}
set => this.structuralOutline = value;
}
///
/// Gets the length.
///
/// Property description.
public int Length => this.HarmonicStructures.Count;
///
/// Gets the bar metric code.
///
/// Returns value.
public string GetBarMetricCode => this.barMetricCode?.Trim();
///
/// Gets the harmonic modality code.
///
/// Returns value.
public string GetHarmonicModalityCode => this.harmonicModalityCode?.Trim();
#endregion
#region Physical properties - Public
///
/// Gets or sets the harmonic behavior.
///
///
/// The harmonic behavior.
///
public HarmonicBehavior HarmonicBehavior { get; set; }
///
/// Gets or sets the rhythmic behavior.
///
///
/// The rhythmic behavior.
///
public RhythmicBehavior RhythmicBehavior { get; set; }
///
/// Gets or sets the rhythmic structure.
///
///
/// General musical property.
///
public RhythmicStructure RhythmicStructure {
get {
//// Contract.Requires(this.RhythmicSystemFromStructures != null);
if (this.rhythmicStructure != null) {
return this.rhythmicStructure;
}
byte rorder = 0; //// ?!?!?
if (this.Header != null) {
rorder = this.Header.System.RhythmicOrder;
}
var musicalHeader = this.Header;
if (musicalHeader != null) {
var system = musicalHeader.System;
//// if (HarmonicMotive?.Core != null) {
rorder = system.RhythmicOrder;
//// }
}
var rsystem = rorder > 0 ? RhythmicSystem.GetRhythmicSystem(RhythmicDegree.Structure, rorder) : this.RhythmicSystemFromStructures;
if (rsystem == null) {
return null;
//// throw new InvalidOperationException("Unknown Rhythmic System.");
}
this.RhythmicShape = this.RhythmicShapeFromStructures(rsystem);
var rs = new RhythmicStructure(rsystem.Order, this.RhythmicShape);
return rs;
}
set => this.rhythmicStructure = value;
}
#endregion
#region Properties - Rhythmic Status
/// Gets or sets rhythmical shape.
/// Property description.
public RhythmicShape RhythmicShape { get; set; }
#endregion
#region Public properties - String representation
/// Gets Write particular structures to string.
/// Returns value.
/// General musical property.
public string PureChordsToString {
get {
var s = new StringBuilder();
//// s.Append("Chords:"); //// +"\n"
byte lev = 0;
foreach (var hs in this.HarmonicStructures.Where(hs => (hs != null && this.RhythmicShape != null) && this.RhythmicShape.Number > 0)) {
var duration = this.RhythmicShape.DistanceAtLevel(lev++);
s.AppendFormat(CultureInfo.CurrentCulture, "{0,15} ", hs.ToneSchema);
s.AppendFormat(CultureInfo.CurrentCulture, "({0,2}), ", duration.ToString("D", CultureInfo.CurrentCulture.NumberFormat));
}
return s.ToString().Trim();
}
}
///
/// Gets modality as string.
///
/// General musical property.
/// Returns value.
public string ModalityToString {
get {
var s = new StringBuilder();
if (this.HarmonicStructures.Count <= 0) {
return s.ToString();
}
var harStruct = this.HarmonicStructures[0];
if (harStruct?.HarmonicModality != null) {
s.AppendFormat(CultureInfo.CurrentCulture, "{0,20} ", harStruct.HarmonicModality.ToneSchema);
}
return s.ToString();
}
}
/// Gets particular structures to string.
/// Property description.
/// Returns value.
[UsedImplicitly]
public string ModalitiesToString {
get {
var s = new StringBuilder();
//// byte lev = 0; //// byte duration;
long lastNumber = 0;
// ReSharper disable once LoopCanBePartlyConvertedToQuery
foreach (var hs in this.HarmonicStructures
.Where(hs => hs?.HarmonicModality != null)) {
if (hs.HarmonicModality.Number == lastNumber) {
continue;
}
//// duration = RhythmicShape.DistanceAtLevel(lev++);
s.Append(hs.HarmonicModality.ToneSchema + "\r");
lastNumber = hs.HarmonicModality.Number;
}
return s.ToString();
}
}
///
/// Gets to string.
///
/// General musical property.
public string ChordsToString {
get {
var s = new StringBuilder();
//// s.Append("Chords:"); //// +"\n"
byte level = 0;
foreach (var hs in this.HarmonicStructures.Where(hs => hs != null && this.RhythmicShape != null)) {
var duration = this.RhythmicShape.DistanceAtLevel(level++);
s.AppendFormat(CultureInfo.CurrentCulture, "{0,15}", hs.HarmonicModality != null ? hs.HarmonicModality.ToneSchema : string.Empty);
s.AppendFormat(CultureInfo.CurrentCulture, "{0,15}", hs.ToneSchema);
s.AppendFormat(CultureInfo.CurrentCulture, "({0,2}),", duration.ToString("D", CultureInfo.CurrentCulture.NumberFormat));
}
return s.ToString().Trim();
}
}
#endregion
#region Public properties
/// Gets inner measure of dissonance.
/// Property description.
public float MeanConsonance {
get {
if (this.Length == 0) {
return 0;
}
var total = (from HarmonicStructure s in this.HarmonicStructures select s.HarmonicBehavior.Consonance).Sum();
var meanConsonance = total / this.Length;
return meanConsonance;
}
}
/// Gets inner continuity.
/// Property description.
public float MeanPotential {
get {
if (this.Length == 0) {
return 0;
}
float total = 0;
var cnt = 0;
foreach (var s in this.HarmonicStructures) {
if (s != null) {
total += s.HarmonicBehavior.Potential;
cnt++;
}
}
var result = cnt != 0 ? total / cnt : 0;
return result;
}
}
/// Gets inner continuity.
/// Property description.
public float MeanContinuity {
get {
if (this.Length == 0) {
return 0;
}
HarmonicStructure p = null;
float total = 0;
var cnt = 0;
foreach (var s in this.HarmonicStructures) {
if (p != null) {
var r = new HarmonicRelation(s.HarmonicSystem, p, s);
total += r.FormalContinuity;
cnt++;
}
p = s;
}
var result = cnt != 0 ? total / cnt : 100;
return result;
}
}
/// Gets inner impulse.
/// Property description.
public float MeanImpulse {
get {
if (this.Length == 0) {
return 0;
}
HarmonicStructure p = null;
float total = 0;
var cnt = 0;
foreach (var s in this.HarmonicStructures) {
if (p != null) {
var r = new HarmonicRelation(s.HarmonicSystem, p, s);
total += r.FormalImpulse;
cnt++;
}
p = s;
}
var result = cnt != 0 ? total / cnt : 0;
return result;
}
}
///
/// Gets the mean rhythmic mobility.
///
public float MeanRhythmicMobility {
get {
//// Contract.Requires(this.RhythmicSystemFromStructures != null);
var rs = this.RhythmicStructure;
if (!rs.HasProperties) {
rs.DetermineBehavior();
}
return rs.RhythmicBehavior.Mobility;
}
}
///
/// Gets the mean rhythmic tension.
///
public float MeanRhythmicTension {
get {
Contract.Requires(this.RhythmicSystemFromStructures != null);
var rs = this.RhythmicStructure;
if (!rs.HasProperties) {
rs.DetermineBehavior();
}
return rs.FormalBehavior.Variance;
}
}
///
/// Gets the rhythmic system from structures.
///
private RhythmicSystem RhythmicSystemFromStructures {
get {
var structures = this.HarmonicStructures;
var rhythmicOrder = structures.Aggregate(0, (current, structure) => (byte)(current + structure.Length));
if (rhythmicOrder == 0) {
return null;
}
var rsystem = RhythmicSystem.GetRhythmicSystem(RhythmicDegree.Shape, rhythmicOrder);
return rsystem;
}
}
#endregion
#region Public static methods
///
/// Empties the bar.
///
/// The harmonic order.
/// The rhythmic order.
///
/// Returns value.
///
public static HarmonicBar EmptyBar(byte harmonicOrder, byte rhythmicOrder) {
var harmonicBar = new HarmonicBar(0, 0);
var structuralCode = string.Empty; //// new byte[0];
var system = HarmonicSystem.GetHarmonicSystem(harmonicOrder);
var hs = new HarmonicStructure(system, structuralCode) {
BitFrom = 0,
Length = rhythmicOrder
};
harmonicBar.AddStructure(hs);
return harmonicBar;
}
#endregion
#region Public methods
///
/// Sets the structure.
///
/// The harmonic structure.
public void SetStructure(HarmonicStructure harmonicStructure) {
this.simpleStructuralOutline = null;
this.structuralOutline = null;
this.RhythmicBehavior = new RhythmicBehavior();
this.HarmonicBehavior = new HarmonicBehavior();
this.harmonicStructures = new List();
this.AddStructure(harmonicStructure);
if (this.RhythmicStructure != null) {
var rhyStruct = this.RhythmicStructure;
var shape = new RhythmicShape(rhyStruct.RhythmicSystem.Order, rhyStruct);
this.SetBarMetricCode(shape.GetStructuralCode);
}
}
///
/// Returns a that represents this instance.
///
///
/// A that represents this instance.
///
public override string ToString() {
var s = new StringBuilder();
s.AppendFormat(CultureInfo.CurrentCulture, "Bar n.{0,3}: ", this.BarNumber); //\r\n
s.Append(this.SimpleStructuralOutline);
return s.ToString();
}
/// Makes a deep copy of the HarmonicBar object.
///
/// Returns object.
///
public object Clone() {
var bar = new HarmonicBar(0, this.OriginalBarNumber) {
Header = this.Header,
HarmonicStructures = this.HarmonicStructures
};
bar.SetBarMetricCode(this.GetBarMetricCode);
bar.SetHarmonicModalityCode(this.GetHarmonicModalityCode);
this.RegenerateStructures();
return bar;
}
///
/// Adds the motive.
///
/// The structure.
public void AddStructure(HarmonicStructure structure) {
((List)this.HarmonicStructures).Add(structure);
}
///
/// Determines the bar metric.
///
/// The rhythmic system.
/// Returns value.
public string BarMetricFromStructures(RhythmicSystem rhythmicSystem) {
//// rewrite it with help of constructor using BitArray
if (rhythmicSystem == null) {
return string.Empty;
}
var barMetric = new BinaryStructure(rhythmicSystem, 0);
byte start = 0;
foreach (var hs in this.HarmonicStructures) {
barMetric.On(start);
start += hs.Length;
}
barMetric.DetermineLevel();
return barMetric.GetStructuralCode;
}
///
/// Sets the bar metric code.
///
/// The given code.
public void SetBarMetricCode(string givenCode) {
this.barMetricCode = givenCode;
}
///
/// Sets the harmonic modality code.
///
/// The given code.
public void SetHarmonicModalityCode(string givenCode) {
this.harmonicModalityCode = givenCode;
}
///
/// Re-computes this instance.
///
public void Recompute() {
if (this.Length == 0 || this.RhythmicStructure == null) {
return;
}
this.HarmonicBehavior.Consonance = this.MeanConsonance;
if (this.HarmonicModality != null) {
this.HarmonicBehavior.Potential = this.MeanPotential;
}
this.HarmonicBehavior.Continuity = this.MeanContinuity;
this.HarmonicBehavior.Impulse = this.MeanImpulse;
this.RhythmicBehavior.Mobility = this.MeanRhythmicMobility;
this.RhythmicBehavior.Tension = this.MeanRhythmicTension;
}
///
/// Checks the structures.
///
public void CheckStructures() {
if (!this.HarmonicStructures.Any()) {
var harmonicOrder = this.Header.System.HarmonicOrder;
//// throw new ArgumentException("Empty har.motive bar structs!");
var harSys = HarmonicSystem.GetHarmonicSystem(harmonicOrder);
var harStr = new HarmonicStructure(harSys, 0L);
//// harStr.DetermineBehavior();
this.AddHarmonicStructure(harStr);
}
}
///
/// Regenerates the structures.
///
public void RegenerateStructures() {
if (this.Header == null) {
return;
}
var harmonicOrder = this.Header.System.HarmonicOrder;
//// var rhythmicOrder = this.Header.System.RhythmicOrder;
var harStructures = new List();
//// Microtonal support
//// harStructNumber = GeneralSystem.ConvertStruct(harStructNumber, hms.HarmonicOrder, harSys.Order); //// harSys.Degree
//// Do not convert to Linq!
foreach (var hms in this.HarmonicStructures) {
if (hms == null) {
continue;
}
var harSys = HarmonicSystem.GetHarmonicSystem(harmonicOrder);
var structuralCode = hms.GetStructuralCode;
var harStruct = HarmonicStructure.GetNewHarmonicStructure(harSys, structuralCode);
//// harStr.DetermineBehavior();
harStruct.BitFrom = hms.BitFrom;
harStruct.Length = hms.Length;
harStructures.Add(harStruct);
}
this.HarmonicStructures = harStructures;
}
/// Returns harmonic structure at given position.
/// Property description.
/// Requested level.
/// Returns value.
public HarmonicStructure HarmonicStructureAtRhythmicLevel(byte givenLevel) {
if (this.HarmonicStructures.Count == 0 || givenLevel >= this.HarmonicStructures.Count) {
return null;
}
return this.HarmonicStructures[givenLevel];
}
/// Returns harmonic structure at given bit.
/// Requested tick.
/// Returns value.
public HarmonicStructure HarmonicStructureAtTick(byte givenTick) {
if (this.RhythmicShape == null) {
return null;
}
var level = this.RhythmicShape.LevelOfBit(givenTick);
return this.HarmonicStructureAtRhythmicLevel(level);
}
///
/// Returns harmonic structure that prevails in given time Range.
///
/// Tone Range.
/// Single Harmony.
/// Returns value.
public HarmonicStructure PrevailingHarmonicStructure(BitRange toneRange, out bool simpleHarmony) {
simpleHarmony = false;
if (this.RhythmicShape == null) {
return null;
}
byte extremeLength = 0, rhythmicLevelAtExtreme = 0;
var level = this.RhythmicShape.Level;
for (byte i = 0; i < level; i++) {
var rhythmicRange = this.RhythmicShape.RangeForLevel(i);
var single = rhythmicRange.CoverRange(toneRange); // 2008/12
if (single) {
simpleHarmony = true;
return this.HarmonicStructureAtRhythmicLevel(i);
}
var interRange = rhythmicRange.IntersectionWith(toneRange);
if (interRange == null || interRange.Length <= extremeLength) {
continue;
}
extremeLength = interRange.Length;
rhythmicLevelAtExtreme = i;
}
//// simpleHarmony = false;
return this.HarmonicStructureAtRhythmicLevel(rhythmicLevelAtExtreme);
}
/// Returns number of bits containing given pitch element.
/// Element of pitch.
/// Given range.
/// Returns value.
[UsedImplicitly]
public int TotalHarmonicBits(byte givenPitchElement, BitRange range) {
if (range == null) {
return 0;
}
byte i, total = 0;
byte bitFrom = range.BitFrom, bitTo = range.BitTo;
for (i = bitFrom; i <= bitTo; i++) {
var harmonicStructure = this.HarmonicStructureAtTick(i);
if (harmonicStructure != null) {
total += (byte)(harmonicStructure.IsOn(givenPitchElement) ? 1 : 0);
}
}
return total;
}
#endregion
#region Private methods
///
/// Rhythmic shape from structures.
///
/// The rhythmic system.
/// Returns value.
private RhythmicShape RhythmicShapeFromStructures(RhythmicSystem rhythmicSystem) {
var bitArray = new BitArray(rhythmicSystem.Order);
var shape = new RhythmicShape(rhythmicSystem, bitArray);
byte start = 0;
foreach (var hs in this.HarmonicStructures) {
if (start < shape.Order) { //// 2015/01
shape.On(start);
}
start += hs.Length;
}
return shape;
}
///
/// Add Harmonic Struct.
///
/// Harmonic structure.
private void AddHarmonicStructure(HarmonicStructure harmonicStructure) {
if (harmonicStructure != null) { //// && !harmonicStructure.IsEmptyStruct() !?
//// // harStr.HarmonicModality = aHarmonicVariety.HarmonicModality;
this.HarmonicStructures.Add(harmonicStructure);
}
}
#endregion
}
}